package cz.muni.fi.pa165.sme.web.panels.sportActivityRecord;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import cz.muni.fi.pa165.sme.api.SportActivityRecordService;
import cz.muni.fi.pa165.sme.api.to.SportActivityRecordTO;
import cz.muni.fi.pa165.sme.web.common.TrackerDataTable;
import cz.muni.fi.pa165.sme.web.fo.SportActivityRecordFO;
import cz.muni.fi.pa165.sme.web.pages.sportActivityRecord.RecordDetailPage;
import cz.muni.fi.pa165.sme.web.pages.sportActivityRecord.RecordEditPage;
import cz.muni.fi.pa165.sme.web.pages.sportActivityRecord.RecordListPage;
import cz.muni.fi.pa165.sme.web.panels.ClickablePropertyColumn;
import cz.muni.fi.pa165.sme.web.panels.DeletePanel;
import cz.muni.fi.pa165.sme.web.panels.EditPanel;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.springframework.core.convert.ConversionService;

/**
 * Displays table of provided {@link SportActivityRecordFO}s
 *
 * @author jirankova
 */
public class RecordListPanel extends Panel {

	@SpringBean
	private SportActivityRecordService sportActivityRecordService;

	@SpringBean(name = "conversionServiceFe")
	private ConversionService conversionService;

	private final NumberFormat numberFormat;
	private final DateFormat dateFormat;

	public RecordListPanel(final String id, final List<SportActivityRecordFO> sportActivityRecordFOs) {
		super(id);

		numberFormat = NumberFormat.getNumberInstance(getLocale());
		dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, getLocale());

		final WebMarkupContainer recordsTable = new TrackerDataTable<SportActivityRecordFO>("recordTable",
				getColumns(),
				new RecordDataProvider(sportActivityRecordFOs));
		recordsTable.setOutputMarkupId(true);
		add(recordsTable);
	}


	/**
	 * Columns for activity record table
	 * @return list of columns
	 */
	private List<IColumn<SportActivityRecordFO>> getColumns() {
		final List<IColumn<SportActivityRecordFO>> columns = new ArrayList<IColumn<SportActivityRecordFO>>();

		columns.add(
				new ClickablePropertyColumn<SportActivityRecordFO>(new ResourceModel("activityName"), "activityName") {
					@Override
					protected void onClick(final IModel<SportActivityRecordFO> rowModel) {
						setResponsePage(new RecordDetailPage(rowModel.getObject()));
					}

					@Override
					public void populateItem(final Item<ICellPopulator<SportActivityRecordFO>> cellItem,
							final String componentId,
							final IModel<SportActivityRecordFO> rowModel) {
						cellItem.add(new Label(componentId, rowModel.getObject().getSportActivity().getTitle()));
					}
				});

		//activity start
		columns.add(new PropertyColumn<SportActivityRecordFO>(new ResourceModel("activityStart"), "activityStart") {
			@Override
			public void populateItem(final Item<ICellPopulator<SportActivityRecordFO>> item, final String componentId,
					final IModel<SportActivityRecordFO> rowModel) {
				item.add(new Label(componentId, dateFormat.format(rowModel.getObject().getActivityStart())));
			}
		});

		//distance
		columns.add(new PropertyColumn<SportActivityRecordFO>(new ResourceModel("distance"), "distance") {
			@Override
			public void populateItem(final Item<ICellPopulator<SportActivityRecordFO>> item, final String componentId,
					final IModel<SportActivityRecordFO> rowModel) {
				if(rowModel.getObject().getDistance() != null) {
					item.add(new Label(componentId, numberFormat.format(rowModel.getObject().getDistance())));
				} else {
					item.add(new Label(componentId, ""));
				}
			}
		});

		//duration
		columns.add(new PropertyColumn<SportActivityRecordFO>(new ResourceModel("duration"), "duration") {
			@Override
			public void populateItem(final Item<ICellPopulator<SportActivityRecordFO>> item, final String componentId,
					final IModel<SportActivityRecordFO> rowModel) {
				item.add(new Label(componentId, numberFormat.format(rowModel.getObject().getDuration())));
			}
		});

		columns.add(new EditColumn(new ResourceModel("edit")));

		columns.add(new RemoveColumn(new ResourceModel("remove")));

		return columns;
	}

	private class EditColumn extends AbstractColumn<SportActivityRecordFO> {
		private EditColumn(final IModel<String> displayModel) {
			super(displayModel);
		}

		@Override
		public void populateItem(final Item<ICellPopulator<SportActivityRecordFO>> cellItem, final String componentId,
				final IModel<SportActivityRecordFO> rowModel) {
			cellItem.add(new EditPanel(componentId, rowModel) {
				@Override
				public void onEdit() {
					setResponsePage(new RecordEditPage(rowModel.getObject()));
				}
			});
		}
	}

	private class RecordDataProvider extends SortableDataProvider<SportActivityRecordFO> {
		private final List<SportActivityRecordFO> activityRecordFOList;

		public RecordDataProvider(final List<SportActivityRecordFO> recordFOs) {
			activityRecordFOList = recordFOs;
			setSort("activityStart", SortOrder.ASCENDING);
		}

		@Override
		public Iterator<? extends SportActivityRecordFO> iterator(final int first, final int count) {
			return activityRecordFOList.subList(first, first + count).iterator();
		}

		@Override
		public int size() {
			return activityRecordFOList.size();
		}

		@Override
		public IModel<SportActivityRecordFO> model(final SportActivityRecordFO object) {
			return new CompoundPropertyModel<SportActivityRecordFO>(
					new LoadableDetachableModel<SportActivityRecordFO>() {
						@Override
						protected SportActivityRecordFO load() {
							return object;
						}
					});
		}

	}


	/**
	 * Column to remove sport activity record
	 */
	private class RemoveColumn extends AbstractColumn<SportActivityRecordFO> {
		public RemoveColumn(final IModel<String> displayModel) {
			super(displayModel);
		}

		@Override
		public void populateItem(final Item<ICellPopulator<SportActivityRecordFO>> cellItem, final String componentId,
				final IModel<SportActivityRecordFO> rowModel) {
			cellItem.add(new DeletePanel(componentId, rowModel) {
				@Override
				public void onDelete() {
					final SportActivityRecordFO activityRecordFO = rowModel.getObject();
					sportActivityRecordService.deleteSportActivityRecord(
							conversionService.convert(activityRecordFO, SportActivityRecordTO.class));
					setResponsePage(RecordListPage.class);
				}
			});
		}
	}
}
